from typing import List, Dict, Optional
from models import Character, Accusation, Case
from ai_service import AIService

class AccusationSystem:
    """指控和反驳系统"""
    
    def __init__(self, ai_service: AIService, evidence_system=None):
        self.ai_service = ai_service
        self.evidence_system = evidence_system
    
    async def conduct_accusation_trial(self, 
                                     accused: Character, 
                                     accuser_reasoning: str,
                                     case: Case,
                                     conversation_history: Dict[str, List[Dict]]) -> Accusation:
        """进行完整的指控审判流程"""
        
        accusation = Accusation(
            accused=accused,
            accuser_reasoning=accuser_reasoning,
            witness_testimonies=[],
            votes=[],
            vote_summary={"support": 0, "oppose": 0, "total": 0}
        )
        
        # 1. 被指控者反驳
        accusation.accused_defense = await self._generate_defense(
            accused, accuser_reasoning, case, conversation_history
        )
        
        # 2. 收集其他角色的证词
        witnesses = [char for char in case.characters 
                    if char.name != accused.name and char.character_type.value != "expert"]
        
        for witness in witnesses:
            testimony = await self._generate_witness_testimony(
                witness, accused, accuser_reasoning, case, conversation_history
            )
            accusation.witness_testimonies.append((witness, testimony))
        
        # 3. 进行投票
        await self._conduct_voting(accusation, case, conversation_history)
        
        # 4. 根据投票结果判断最终结果（过半数支持才算成功）
        total_voters = accusation.vote_summary["total"]
        support_votes = accusation.vote_summary["support"]
        accusation.final_verdict = support_votes > total_voters / 2
        
        return accusation
    
    async def conduct_streaming_accusation_trial(self, 
                                               accused: Character, 
                                               accuser_reasoning: str,
                                               case: Case,
                                               conversation_history: Dict[str, List[Dict]],
                                               ui) -> Accusation:
        """进行流式输出的指控审判流程"""
        
        accusation = Accusation(
            accused=accused,
            accuser_reasoning=accuser_reasoning,
            witness_testimonies=[],
            votes=[],
            vote_summary={"support": 0, "oppose": 0, "total": 0}
        )
        
        # 1. 流式显示被指控者反驳
        ui.console.print(f"\n🛡️ {accused.name}为自己辩护：")
        defense_stream = await self._generate_defense_stream(
            accused, accuser_reasoning, case, conversation_history
        )
        accusation.accused_defense = await ui.show_streaming_defense(accused, defense_stream)
        input("\n按回车键继续...")
        
        # 2. 流式显示证人证词
        witnesses = [char for char in case.characters 
                    if char.name != accused.name and char.character_type.value != "expert"]
        
        ui.console.print(f"\n👥 证人作证环节：")
        for witness in witnesses:
            ui.console.print(f"\n📢 {witness.name}({witness.occupation})作证：")
            testimony_stream = await self._generate_witness_testimony_stream(
                witness, accused, accuser_reasoning, case, conversation_history
            )
            testimony = await ui.show_streaming_testimony(witness, testimony_stream)
            accusation.witness_testimonies.append((witness, testimony))
            input("\n按回车键继续...")
        
        # 3. 进行投票
        ui.console.print(f"\n🗳️ 投票环节：")
        await self._conduct_streaming_voting(accusation, case, conversation_history, ui)
        
        # 4. 根据投票结果判断最终结果（过半数支持才算成功）
        total_voters = accusation.vote_summary["total"]
        support_votes = accusation.vote_summary["support"]
        accusation.final_verdict = support_votes > total_voters / 2
        
        return accusation
    
    async def _generate_defense(self, 
                               accused: Character, 
                               accuser_reasoning: str,
                               case: Case,
                               conversation_history: Dict[str, List[Dict]]) -> str:
        """生成被指控者的反驳"""
        
        # 获取被指控者的完整对话历史
        accused_conversations = conversation_history.get(accused.name, [])
        conversation_context = ""
        if accused_conversations:
            conversation_context = "【我与侦探的完整对话记录】\n"
            for i, conv in enumerate(accused_conversations, 1):
                conversation_context += f"第{i}轮对话：\n"
                conversation_context += f"侦探问：{conv['question']}\n"
                conversation_context += f"我答：{conv['response']}\n\n"
        else:
            conversation_context = "【我与侦探没有进行过对话】"
        
        # 获取在场人员
        present_people = [char.name for char in case.characters 
                         if char.name != accused.name and char.character_type.value != "expert"]
        present_people_str = "、".join(present_people)
        
        prompt = f"""你正在扮演被指控的{accused.name}，现在侦探指控你是凶手，你需要为自己辩护。

【你的角色设定】
我是{accused.name}，{accused.age}岁，{accused.occupation}。
性格：{accused.personality}
背景：{accused.background}
我的秘密：{accused.secret}
我的不在场证明：{accused.alibi}
{"我的动机：" + accused.motive if accused.motive else ""}

【案件情况】
{case.description}
受害者是{case.victim_name}，案发时间{case.time_of_crime}，地点在{case.crime_scene}。

【侦探的指控】
侦探指控我是凶手，理由是：{accuser_reasoning}

【我之前的对话】
{conversation_context if conversation_context else "没有进行过对话"}

【在场人员】
当晚在场的还有：{present_people_str}

【反驳要求】
1. 以第一人称进行反驳，符合我的性格
2. {"如果我确实是凶手，要巧妙反驳但不能撒谎太明显，可以转移注意力或质疑证据" if accused.is_guilty else "我是无辜的，要据理力争，指出指控的漏洞"}
3. 可以提到我的不在场证明
4. 可以暗示其他人更可疑
5. 反驳要有逻辑性，不要太长
6. 表现出相应的情绪（愤怒、委屈、震惊等）

我的反驳："""

        try:
            response = await self.ai_service.get_fast_response(prompt)
            return response.strip()
        except Exception as e:
            return f"[{accused.name}显得很震惊，一时说不出话来]"
    
    async def _generate_defense_stream(self, 
                                     accused: Character, 
                                     accuser_reasoning: str,
                                     case: Case,
                                     conversation_history: Dict[str, List[Dict]]):
        """生成被指控者的流式反驳"""
        
        # 获取被指控者的完整对话历史
        accused_conversations = conversation_history.get(accused.name, [])
        conversation_context = ""
        if accused_conversations:
            conversation_context = "【我与侦探的完整对话记录】\n"
            for i, conv in enumerate(accused_conversations, 1):
                conversation_context += f"第{i}轮对话：\n"
                conversation_context += f"侦探问：{conv['question']}\n"
                conversation_context += f"我答：{conv['response']}\n\n"
        else:
            conversation_context = "【我与侦探没有进行过对话】"
        
        # 获取在场人员
        present_people = [char.name for char in case.characters 
                         if char.name != accused.name and char.character_type.value != "expert"]
        present_people_str = "、".join(present_people)
        
        prompt = f"""你正在扮演被指控的{accused.name}，现在侦探指控你是凶手，你需要为自己辩护。

【你的角色设定】
我是{accused.name}，{accused.age}岁，{accused.occupation}。
性格：{accused.personality}
背景：{accused.background}
我的秘密：{accused.secret}
我的不在场证明：{accused.alibi}
{"我的动机：" + accused.motive if accused.motive else ""}

【案件情况】
{case.description}
受害者是{case.victim_name}，案发时间{case.time_of_crime}，地点在{case.crime_scene}。

【侦探的指控】
侦探指控我是凶手，理由是：{accuser_reasoning}

{conversation_context}

【在场人员】
当晚在场的还有：{present_people_str}

【反驳要求】
1. 以第一人称进行反驳，符合我的性格
2. {"如果我确实是凶手，要巧妙反驳但不能撒谎太明显，可以转移注意力或质疑证据" if accused.is_guilty else "我是无辜的，要据理力争，指出指控的漏洞"}
3. 可以提到我的不在场证明
4. 可以暗示其他人更可疑
5. 反驳要有逻辑性，不要太长
6. 表现出相应的情绪（愤怒、委屈、震惊等）

我的反驳："""

        try:
            return self.ai_service.get_stream_response(prompt)
        except Exception as e:
            async def error_stream():
                yield f"[{accused.name}显得很震惊，一时说不出话来]"
            return error_stream()
    
    async def _generate_witness_testimony(self,
                                        witness: Character,
                                        accused: Character,
                                        accuser_reasoning: str,
                                        case: Case,
                                        conversation_history: Dict[str, List[Dict]]) -> str:
        """生成证人证词"""
        
        # 获取证人的完整对话历史
        witness_conversations = conversation_history.get(witness.name, [])
        conversation_context = ""
        if witness_conversations:
            conversation_context = "【我与侦探的完整对话记录】\n"
            for i, conv in enumerate(witness_conversations, 1):
                conversation_context += f"第{i}轮对话：\n"
                conversation_context += f"侦探问：{conv['question']}\n"
                conversation_context += f"我答：{conv['response']}\n\n"
        else:
            conversation_context = "【我与侦探没有进行过对话】"
        
        prompt = f"""你正在扮演{witness.name}，现在侦探指控{accused.name}是凶手，你需要作为证人发表看法。

【你的角色设定】
我是{witness.name}，{witness.age}岁，{witness.occupation}。
性格：{witness.personality}
背景：{witness.background}
我的秘密：{witness.secret}
我知道的信息：{chr(10).join(witness.knowledge)}

【案件情况】
{case.description}
受害者是{case.victim_name}，案发时间{case.time_of_crime}。

【指控情况】
侦探指控{accused.name}是凶手，理由是：{accuser_reasoning}

【我之前的对话】
{conversation_context if conversation_context else "没有进行过对话"}

【证词要求】
1. 以第一人称发表看法，符合我的性格
2. 基于我知道的信息和观察到的情况
3. {"如果我是真凶，要巧妙地支持对{accused.name}的指控，转移注意力" if witness.is_guilty else "诚实地说出我的观察和看法"}
4. 可以提到当晚观察到的{accused.name}的行为
5. 可以支持或质疑这个指控
6. 证词要简洁，不要太长

我的证词："""

        try:
            response = await self.ai_service.get_fast_response(prompt)
            return response.strip()
        except Exception as e:
            return f"[{witness.name}沉默了一会儿，似乎在思考]"
    
    async def _generate_witness_testimony_stream(self,
                                               witness: Character,
                                               accused: Character,
                                               accuser_reasoning: str,
                                               case: Case,
                                               conversation_history: Dict[str, List[Dict]]):
        """生成证人证词的流式输出"""
        
        # 获取证人的完整对话历史
        witness_conversations = conversation_history.get(witness.name, [])
        conversation_context = ""
        if witness_conversations:
            conversation_context = "【我与侦探的完整对话记录】\n"
            for i, conv in enumerate(witness_conversations, 1):
                conversation_context += f"第{i}轮对话：\n"
                conversation_context += f"侦探问：{conv['question']}\n"
                conversation_context += f"我答：{conv['response']}\n\n"
        else:
            conversation_context = "【我与侦探没有进行过对话】"
        
        prompt = f"""你正在扮演{witness.name}，现在侦探指控{accused.name}是凶手，你需要作为证人发表看法。

【你的角色设定】
我是{witness.name}，{witness.age}岁，{witness.occupation}。
性格：{witness.personality}
背景：{witness.background}
我的秘密：{witness.secret}
我知道的信息：{chr(10).join(witness.knowledge)}

【案件情况】
{case.description}
受害者是{case.victim_name}，案发时间{case.time_of_crime}。

【指控情况】
侦探指控{accused.name}是凶手，理由是：{accuser_reasoning}

{conversation_context}

【证词要求】
1. 以第一人称发表看法，符合我的性格
2. 基于我知道的信息和观察到的情况
3. {"如果我是真凶，要巧妙地支持对{accused.name}的指控，转移注意力" if witness.is_guilty else "诚实地说出我的观察和看法"}
4. 可以提到当晚观察到的{accused.name}的行为
5. 可以支持或质疑这个指控
6. 证词要简洁，不要太长

我的证词："""

        try:
            return self.ai_service.get_stream_response(prompt)
        except Exception as e:
            async def error_stream():
                yield f"[{witness.name}沉默了一会儿，似乎在思考]"
            return error_stream()
    
    async def _conduct_voting(self, 
                            accusation: Accusation, 
                            case: Case,
                            conversation_history: Dict[str, List[Dict]]):
        """进行投票环节"""
        
        # 获取所有投票者（除了被指控者）
        voters = [char for char in case.characters 
                 if char.name != accusation.accused.name and char.character_type.value != "expert"]
        
        support_count = 0
        oppose_count = 0
        
        for voter in voters:
            vote_result, vote_reason = await self._generate_vote(
                voter, accusation, case, conversation_history
            )
            
            accusation.votes.append((voter, vote_result, vote_reason))
            
            if vote_result == "支持":
                support_count += 1
            else:
                oppose_count += 1
        
        # 更新投票统计
        accusation.vote_summary = {
            "support": support_count,
            "oppose": oppose_count,
            "total": len(voters)
        }
    
    async def _conduct_streaming_voting(self, 
                                      accusation: Accusation, 
                                      case: Case,
                                      conversation_history: Dict[str, List[Dict]],
                                      ui):
        """进行流式投票环节"""
        
        # 获取所有投票者（除了被指控者）
        voters = [char for char in case.characters 
                 if char.name != accusation.accused.name and char.character_type.value != "expert"]
        
        support_count = 0
        oppose_count = 0
        
        for voter in voters:
            ui.console.print(f"\n🗳️ {voter.name}({voter.occupation})正在投票...")
            
            vote_result, vote_reason = await self._generate_vote(
                voter, accusation, case, conversation_history
            )
            
            accusation.votes.append((voter, vote_result, vote_reason))
            
            # 显示投票结果
            vote_color = "green" if vote_result == "支持" else "red"
            vote_icon = "✅" if vote_result == "支持" else "❌"
            
            from rich.panel import Panel
            vote_panel = Panel(
                f"{vote_icon} {voter.name}：{vote_result}指控\n💭 理由：{vote_reason}",
                title=f"{voter.name}的投票",
                border_style=vote_color
            )
            ui.console.print(vote_panel)
            
            if vote_result == "支持":
                support_count += 1
            else:
                oppose_count += 1
            
            input("\n按回车键继续...")
        
        # 更新投票统计
        accusation.vote_summary = {
            "support": support_count,
            "oppose": oppose_count,
            "total": len(voters)
        }
        
        # 显示投票统计
        summary_text = f"""
🗳️ 投票统计：
✅ 支持指控：{support_count}票
❌ 反对指控：{oppose_count}票
📊 总票数：{len(voters)}票

需要过半数({len(voters)//2 + 1}票)支持才能定罪
        """
        
        from rich.panel import Panel
        summary_panel = Panel(
            summary_text,
            title="投票结果统计",
            border_style="cyan"
        )
        ui.console.print(summary_panel)
    
    async def _generate_vote(self,
                           voter: Character,
                           accusation: Accusation,
                           case: Case,
                           conversation_history: Dict[str, List[Dict]]) -> tuple:
        """生成角色的投票和理由"""
        
        # 获取投票者的完整对话历史
        voter_conversations = conversation_history.get(voter.name, [])
        conversation_context = ""
        if voter_conversations:
            conversation_context = "【我与侦探的完整对话记录】\n"
            for i, conv in enumerate(voter_conversations, 1):
                conversation_context += f"第{i}轮对话：\n"
                conversation_context += f"侦探问：{conv['question']}\n"
                conversation_context += f"我答：{conv['response']}\n\n"
        else:
            conversation_context = "【我与侦探没有进行过对话】"
        
        # 获取已有的证词
        testimonies_context = ""
        for witness, testimony in accusation.witness_testimonies:
            if witness.name == voter.name:
                testimonies_context += f"我的证词：{testimony}\n\n"
            else:
                testimonies_context += f"{witness.name}的证词：{testimony}\n\n"
        
        # 分析对话中的矛盾证据
        contradictions = self._analyze_contradictions(accusation.accused, conversation_history)
        
        # 获取证据信息（使用证据系统）
        evidence_info = ""
        if self.evidence_system:
            try:
                evidence_info = await self.evidence_system.get_evidence_for_voting(case, voter)
                evidence_info += "\n"
            except Exception as e:
                # 备用方案：使用基本证据信息
                if case.evidence:
                    evidence_info = "【现场物理证据】\n"
                    for evidence in case.evidence:
                        evidence_info += f"- {evidence.name}：{evidence.description}（发现地点：{evidence.location}）\n"
                    evidence_info += "\n"
        else:
            # 没有证据系统时的备用方案
            if case.evidence:
                evidence_info = "【现场物理证据】\n"
                for evidence in case.evidence:
                    evidence_info += f"- {evidence.name}：{evidence.description}（发现地点：{evidence.location}）\n"
                evidence_info += "\n"
        
        prompt = f"""你正在扮演{voter.name}，现在需要对侦探的指控进行投票。

【你的角色设定】
我是{voter.name}，{voter.age}岁，{voter.occupation}。
性格：{voter.personality}
背景：{voter.background}
我的秘密：{voter.secret}
我知道的信息：{chr(10).join(voter.knowledge)}

【案件基本信息】
受害者：{case.victim_name}
案发时间：{case.time_of_crime}
案发地点：{case.crime_scene}

{evidence_info}【指控情况】
侦探指控{accusation.accused.name}是凶手，理由是：{accusation.accuser_reasoning}

【被告反驳】
{accusation.accused.name}的反驳：{accusation.accused_defense}

【证据分析】
{contradictions}

【证人证词】
{testimonies_context}

{conversation_context}

【投票要求】
1. 你需要投票：支持指控 或 反对指控
2. {"如果你是真凶，应该支持对{accusation.accused.name}的指控，转移注意力" if voter.is_guilty else "作为理性的观察者，综合分析所有证据"}
3. 重点分析以下关键点：
   - 时间线是否存在明显矛盾（如声称的时间与其他人观察不符）
   - 证词前后是否一致（如先说在厨房，后承认去了书房）
   - 行为是否异常可疑（如神色慌张、回避问题）
   - 动机是否充分（如经济纠纷、家庭矛盾、财产争夺）
   - 物理证据是否支持指控（如现场痕迹、凶器等）
4. 如果发现明显的时间线矛盾、证词不一致或有充分动机，应该支持指控
5. 给出详细的投票理由（2-3句话，说明具体的矛盾点或证据）
6. 符合你的性格特点和观察能力

请按以下格式回答：
投票：[支持/反对]
理由：[你的理由]"""

        try:
            response = await self.ai_service.get_fast_response(prompt)
            lines = response.strip().split('\n')
            
            vote_result = "反对"  # 默认值
            vote_reason = "没有足够的证据支持这个指控。"  # 默认理由
            
            for line in lines:
                if line.startswith("投票："):
                    vote_text = line.replace("投票：", "").strip()
                    if "支持" in vote_text:
                        vote_result = "支持"
                    else:
                        vote_result = "反对"
                elif line.startswith("理由："):
                    vote_reason = line.replace("理由：", "").strip()
            
            return vote_result, vote_reason
            
        except Exception as e:
            # 如果AI调用失败，根据角色特点给出默认投票
            if voter.is_guilty:
                return "支持", "我觉得证据很充分。"
            else:
                return "反对", "证据不够充分，需要更多调查。"
    
    def _analyze_contradictions(self, accused: Character, conversation_history: Dict[str, List[Dict]]) -> str:
        """分析被指控者的证词矛盾"""
        accused_conversations = conversation_history.get(accused.name, [])
        
        if not accused_conversations:
            return "没有足够的对话记录进行分析。"
        
        # 收集被指控者的完整证词
        accused_statements = []
        for i, conv in enumerate(accused_conversations, 1):
            accused_statements.append(f"第{i}轮 - 问：{conv['question']}\n      答：{conv['response']}")
        
        # 收集其他人的相关证词
        other_testimonies = []
        for char_name, conversations in conversation_history.items():
            if char_name != accused.name and conversations:
                for i, conv in enumerate(conversations, 1):
                    # 只收集与时间、地点、行为相关的证词
                    if any(keyword in conv['response'] for keyword in ['点', '时间', '书房', '厨房', '看到', '听到']):
                        other_testimonies.append(f"{char_name}第{i}轮证词：{conv['response']}")
        
        analysis = f"""
【{accused.name}的完整证词记录】
{chr(10).join(accused_statements)}

【其他人员的相关证词】
{chr(10).join(other_testimonies)}

【重点分析】
请特别注意以下可能的矛盾：
1. 时间线矛盾：{accused.name}声称的行动时间是否与其他人观察到的时间一致？
2. 地点矛盾：{accused.name}声称的位置是否与其他人的观察一致？
3. 证词变化：{accused.name}在不同轮次的回答是否前后一致？
4. 行为异常：其他人是否观察到{accused.name}的可疑行为？
5. 动机分析：{accused.name}是否有充分的作案动机？

如果发现明显矛盾，应该支持指控；如果证据不足或存在合理解释，应该反对指控。
        """
        
        return analysis 